package com.tuzhi.base.web.controller;

import com.alibaba.fastjson2.JSON;
import com.tuzhi.base.jpa.domain.Pager;
import com.tuzhi.base.jpa.domain.WhereConditionBO;
import com.tuzhi.base.jpa.domain.WhereStatementBO;
import com.tuzhi.base.jpa.healper.WhereConditionHelper;
import com.tuzhi.base.service.BaseService;
import com.tuzhi.base.web.helper.AjaxResultHelper;
import com.tuzhi.base.web.vo.AjaxResultVO;
import com.tuzhi.base.web.vo.PageVO;
import com.tuzhi.common.constants.ResultConstant;
import com.tuzhi.common.domain.ResultBO;
import com.tuzhi.common.helper.ResultHelper;
import com.tuzhi.util.ReflectionTzUtil;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Map;

public abstract class AbsBaseController<T, Pk> {

    private static final Logger log = LoggerFactory.getLogger(AbsBaseController.class);

    protected abstract BaseService getThisService();

    @GetMapping("/list")
    public AjaxResultVO<T> list(@RequestBody(required = false) PageVO pageVO) {
        if (pageVO == null) {
            pageVO = new PageVO();
        }
        PageRequest pageRequest = PageRequest.of(pageVO.queryPage(), pageVO.getSize());
        Page page = getThisService().findPage(pageRequest, transEntity(pageVO.getReqData()));
        pageVO.setData(page.getContent());
        pageVO.setTotalPage(page.getTotalPages());
        pageVO.setTotalNum(page.getTotalElements());
        return AjaxResultHelper.success().ofData(pageVO);

    }

    @GetMapping("/findOne")
    public AjaxResultVO<T> findOne(@RequestBody String json) {
        T t = (T) getThisService().findOne(WhereConditionHelper.trans(json));
        return AjaxResultHelper.success().ofData(t);

    }

    public T findOne(WhereConditionBO whereConditionBO) {
        T t = (T) getThisService().findOne(whereConditionBO);
        return t;

    }

    @PostMapping("/postList")
    public AjaxResultVO<T> postList(@RequestBody(required = false) PageVO pageVO) {
        return list(pageVO);
    }

    @PostMapping("/postFindOne")
    public AjaxResultVO postFindOne(@RequestBody String json) {
        T t = (T) getThisService().findOne(WhereConditionHelper.trans(json));
        return AjaxResultHelper.success().ofData(t);

    }

    @PutMapping("/add")
    public ResultBO<T> add(@RequestBody T t) {
        if (t == null) {
            log.warn("传入参数为空!");
            return ResultHelper.build(ResultConstant.ERR_PARAM_NULL);
        }
//        log.info(t.toString());
        getThisService().save(t);
        return ResultHelper.success();
    }

    @PostMapping("/update")
    public ResultBO<T> update(@RequestBody T t) {
        if (t == null) {
            log.warn("传入参数为空!");
            return ResultHelper.build(ResultConstant.ERR_PARAM_NULL);
        }
//        log.info(t.toString());
        getThisService().save(t);
        return ResultHelper.success();
    }

    @DeleteMapping("/del/{id}")
    public ResultBO<T> del(@PathVariable(value = "id", required = true) Pk id) {
        getThisService().deleteById(id);
        return ResultHelper.success();
    }

    @DeleteMapping("/del4status/{id}")
    public ResultBO<T> del4Status(@PathVariable(value = "id", required = true) Pk id) {
        getThisService().delete4Status(id);
        return ResultHelper.success();
    }

    protected T transEntity(Object obj) {
        Class t = ReflectionTzUtil.getClassT(this, 0);

        if (obj != null && obj instanceof Map) {
            String json = JSON.toJSONString(obj);
            return (T) JSON.parseObject(json, ReflectionTzUtil.getClassT(this, 0));
        } else {
            return (T) ReflectionTzUtil.newInstance(t, new Class[0], null);
        }
    }

    @GetMapping("/get/{pk}")
    public AjaxResultVO<T> get(@PathVariable("pk") Pk pk) {
        T t = (T) getThisService().findById(pk);
        return AjaxResultHelper.success().ofData(t);

    }

    /**
     * 根据分布请求参数和申明，自动查询返回PageVO
     * @param pageVO
     * @param whereStatementBO
     * @return
     */
    protected PageVO findPager(PageVO pageVO, WhereStatementBO whereStatementBO) {
        if (pageVO == null) {
            pageVO = new PageVO();
        }
//        pageVO.setSize(2);
        PageRequest pageRequest = PageRequest.of(pageVO.queryPage(), pageVO.getSize());

        Map map = (Map) pageVO.getReqData();

        WhereConditionBO whereConditionBO = WhereConditionHelper.trans(whereStatementBO, map);
        Page page = getThisService().findPage(pageRequest, whereConditionBO);

        pageVO.setData(page.getContent());
        pageVO.setTotalPage(page.getTotalPages());
        pageVO.setTotalNum(page.getTotalElements());

        return pageVO;
    }

    /**
     * 根据已经组装好的条件进行查询
     * @param pageVO
     * @param whereConditionBO
     * @return
     */
    protected PageVO findPager(PageVO pageVO, WhereConditionBO whereConditionBO) {
        if (pageVO == null) {
            pageVO = new PageVO();
        }
        PageRequest pageRequest = PageRequest.of(pageVO.queryPage(), pageVO.getSize());

        Page page = getThisService().findPage(pageRequest, whereConditionBO);

        pageVO.setData(page.getContent());
        pageVO.setTotalPage(page.getTotalPages());
        pageVO.setTotalNum(page.getTotalElements());

        return pageVO;
    }

    @PostMapping({"/pager"})
    public AjaxResultVO<T> pager(@RequestBody(required = false) PageVO pageVO) {
        try {
            AjaxResultVO ajaxResultVO = AjaxResultHelper.success();
            Pager<T> pager = new Pager<>();
            pager.setPage(pageVO.getPage());
            pager.setSize(pageVO.getSize());
            pager = pagerVoCreateWhere(pageVO, pager);
            pager = getThisService().listPager(pager);
            pageVO.setData(pager.getData());
            pageVO.setTotalPage(pager.getTotalPage());
            pageVO.setTotalNum(pager.getTotalNum());
            ajaxResultVO.setData(pageVO);
            return ajaxResultVO;
        } catch (Exception ex) {
            log.error("分页异常 pager：{}", ExceptionUtils.getStackTrace(ex));
            AjaxResultVO ajaxResultVO = AjaxResultHelper.error();
            ajaxResultVO.setMsg("分页异常");
            return ajaxResultVO;
        }
    }

    /**
     * 把前端传的查询条件转成查询条件
     *
     * @param pageVO
     * @param pager
     */
    public Pager<T> pagerVoCreateWhere(PageVO pageVO, Pager<T> pager) {
        return pager;
    }

    /**
     * 把请求的JSON对象转成对应的VO
     * @param reqData
     * @param eClass
     * @return
     * @param <E>
     */
    protected <E>  E pageReqData2Bean(Object reqData, Class<E> eClass){
        String json = JSON.toJSONString(reqData);
        E vo = JSON.parseObject(json,eClass);
        return vo;
    }

    /**
     * 心跳接口查询
     * @return
     */
    @GetMapping("/test")
    public AjaxResultVO test(){
        log.info("心跳接口测试，接口正常");
        AjaxResultVO ajaxResultVO = AjaxResultHelper.success();
        ajaxResultVO.setMsg("心跳接口测试，接口正常:");
        ajaxResultVO.setData(DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
        return ajaxResultVO;
    }


}
